#pragma once

#include <prerequisites.h>

class scene_saver : public ITreeEnumProc
{
public:
	scene_saver(TimeValue time, bool export_selected);
	virtual ~scene_saver();

	void clear();

	virtual int callback(INode *node);

	size_t get_num_meshes() const;
	size_t get_num_models() const;
	size_t get_num_materials() const;
	size_t get_num_textures() const;
	size_t get_num_skeletons() const;

	mesh_ptr get_mesh(size_t id) const;
	model_ptr get_model(size_t id) const;
	material_ptr get_material(size_t id) const;
	texture_ptr get_texture(size_t id) const;
	skeleton_ptr get_skeleton(size_t id) const;

	virtual bool save(const char *path) = 0;

private:
	typedef std::map<Object*, mesh_vec>		mesh_map;
	typedef std::map<Mtl*, material_vec>	mtl_map;
	typedef std::map<Bitmap*, texture_ptr>	texture_map;
	typedef std::map<Object*, skeleton_ptr>	skeleton_map;
	typedef std::set<std::string>			string_set;

	model_ptr extract_model(INode *node);

	animation_ptr extract_node_animation(INode *node, const matrix4 &tm);
	skeleton_ptr extract_skeletal_animation(INode *node, mesh_vec &meshes);

	mesh_vec extract_meshes(INode *node);
	mesh_ptr extract_mesh(size_t id, Mesh *m, const Matrix3 &tm);

	material_vec extract_materials(Mtl *m);

	texture_ptr extract_texture(BitmapTex *bmt);

	void optimize(mesh_vec &meshes, material_vec &materials);

	void build_normals(mesh_ptr m);

	mesh_vec		m_meshes;
	model_vec		m_models;
	material_vec	m_materials;
	texture_vec		m_textures;
	skeleton_vec	m_skeletons;

	mesh_map		m_meshobj;
	mtl_map			m_mtls;
	texture_map		m_tex;
	skeleton_map	m_skls;

	string_set		m_matids;
	string_set		m_meshids;
	string_set		m_modelids;
	string_set		m_animids;
	string_set		m_sklids;
	string_set		m_jntids;

	bool			m_export_selected;

	TimeValue		m_time;
};

inline size_t scene_saver::get_num_meshes() const { return m_meshes.size(); }

inline size_t scene_saver::get_num_models() const { return m_models.size(); }

inline size_t scene_saver::get_num_materials() const { return m_materials.size(); }

inline size_t scene_saver::get_num_textures() const { return m_textures.size(); }

inline mesh_ptr scene_saver::get_mesh(size_t id) const { return m_meshes[id]; }

inline model_ptr scene_saver::get_model(size_t id) const { return m_models[id]; }

inline material_ptr scene_saver::get_material(size_t id) const { return m_materials[id]; }

inline texture_ptr scene_saver::get_texture(size_t id) const { return m_textures[id]; }

inline size_t scene_saver::get_num_skeletons() const { return m_skeletons.size(); }

inline skeleton_ptr scene_saver::get_skeleton(size_t id) const { return m_skeletons[id]; }